<template>
  <div class="app-container">
    <el-row :gutter="24" class="novel-page">
      <!-- 左侧AI对话区域 -->
      <el-col :span="9" class="novel-page-left">
        <div class="left-panel">
          <div v-if="thinkData && thinkData.length > 0" class="thinking-panel">
            <div class="thinking-header">
              <div class="thinking-title">AI思考过程</div>
              <el-tooltip content="AI在回复前的内部思考过程，帮助您了解AI的推理逻辑" placement="top">
                <el-icon class="help-icon"><QuestionFilled /></el-icon>
              </el-tooltip>
            </div>
            <div class="thinking-content">
              {{ thinkData }}
            </div>
          </div>
          <NovelAiChat
            ref="aiChatRef"
            title="AI世界观设定助手"
            placeholder="请输入您对世界观的要求，例如：我想要一个现代都市背景，但其中隐藏着超自然力量的世界观..."
            :loading="aiLoading"
            :enable-context="enableContext"
            :max-context-messages="10"
            @send="handleAiChat"
            @context-change="handleContextChange"
            @abort="handleAbortAI"
          />
        </div>
      </el-col>

      <!-- 右侧内容编辑区域 -->
      <el-col :span="15" class="novel-page-right">
        <template v-if="currentProject">
          <!-- 项目信息卡片 -->
          <div class="content-header">
            <div class="project-info">
              <div class="project-title">
                <span class="label">项目：</span>
                <span class="value">{{ currentProject.title }}</span>
              </div>
              <el-tag type="info" effect="plain" class="project-tag">世界观设定</el-tag>
            </div>
            <div class="action-buttons">
              <el-tooltip content="保存设定" placement="top">
                <el-button type="primary" :icon="Document" circle @click="handleSave" :loading="saveLoading" />
              </el-tooltip>
              <el-tooltip content="下一步" placement="top" v-if="canGoNext">
                <el-button type="success" :icon="ArrowRight" circle @click="handleNextStep" />
              </el-tooltip>
            </div>
          </div>

          <!-- 世界观设定编辑 -->
          <div class="content-body">
            <div class="form-container">
              <el-form
                ref="worldSettingFormRef"
                :model="form"
                :rules="rules"
                label-width="100px"
                class="setting-form"
              >
                <el-form-item label="设定名称" prop="name">
                  <el-input
                    v-model="form.name"
                    placeholder="请输入世界观设定名称"
                    clearable
                  />
                </el-form-item>
                <el-form-item label="详细描述" prop="content">
                  <div class="content-editor">
                    <div class="editor-toolbar">
                      <div class="toolbar-title">世界观详细设定</div>
                      <div class="ai-status" v-if="isSummaryLoading">
                        <i class="el-icon-loading"></i>
                        AI正在生成中...
                      </div>
                    </div>
                    <el-input
                      v-model="form.content"
                      type="textarea"
                      :rows="16"
                      resize="none"
                      placeholder="请输入世界观详细描述，包括世界背景、规则、特殊设定等内容..."
                      class="content-textarea"
                    />
                  </div>
                </el-form-item>
              </el-form>
            </div>
          </div>
        </template>
        <el-empty v-else description="请先选择或创建一个小说项目" />
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import {ref, computed, onMounted, watch} from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getWorldSetting,getWorldSettingByProject, addWorldSetting, updateWorldSetting } from "@/api/novel/worldSetting"
import { getProject, updateProject } from '@/api/novel/project'
import NovelAiChat from '@/components/NovelAiChat/index.vue'
import { useAIStream, PlatformType, AIModelType } from "@/components/Hook/useStreamFetch"
import { Document, ArrowRight, QuestionFilled } from '@element-plus/icons-vue'

const route = useRoute()
const router = useRouter()

// 项目数据
const currentProject = ref(null)
const loading = ref(false)
const aiLoading = ref(false)
const saveLoading = ref(false)
const currentSetting = ref(null)
const aiChatRef = ref(null)

// 表单参数
const form = ref({
  id: undefined,
  projectId: undefined,
  name: '',
  content: ''
})

const rules = ref({
  name: [
    { required: true, message: '设定名称不能为空', trigger: 'blur' }
  ],
  content: [
    { required: true, message: '详细描述不能为空', trigger: 'blur' }
  ]
})

// 表单引用
const worldSettingFormRef = ref(null)

// 计算属性
const canGoNext = computed(() => {
  return currentProject.value && currentSetting.value
})

// 上下文控制状态
const enableContext = ref(true)

// 获取项目信息
const getProjectInfo = async () => {
  const projectId = route.query.projectId
  if (!projectId) {
    ElMessage.warning('请先选择小说项目')
    router.push('/novel/project')
    return
  }

  try {
    const response = await getProject(projectId.toString())
    currentProject.value = response.data
    form.value.projectId = projectId.toString()
    getWorldSettingInfo()
  } catch (error) {
    console.error('获取项目信息失败:', error)
    ElMessage.error('获取项目信息失败')
  }
}

// 获取世界观设定信息
const getWorldSettingInfo = async () => {
  loading.value = true
  try {
    console.log(currentProject.value.id.toString())
    const response = await getWorldSettingByProject( currentProject.value.id.toString())

    if (response.data ) {
      currentSetting.value = response.data
      console.log(currentSetting.value)
      form.value = {
        id: currentSetting.value.id.toString(),
        projectId: currentSetting.value.projectId.toString(),
        name: currentSetting.value.name,
        content: currentSetting.value.content
      }

      // 如果有现有的世界观设定，将其作为AI的历史回复添加到对话中
      if (currentSetting.value.content) {
        aiChatRef.value.addAiResponse({
          role: "assistant",
          content: `我已经为您创建了以下世界观设定：\n\n${currentSetting.value.content}`
        })
      }
    } else {
      currentSetting.value = null
      form.value = {
        id: undefined,
        projectId: currentProject.value.id.toString(),
        name: '',
        content: ''
      }
    }
  } catch (error) {
    console.error('获取世界观设定信息失败:', error)
    ElMessage.error('获取世界观设定信息失败')
  } finally {
    loading.value = false
  }
}

const difyApi = 'https://ark.cn-beijing.volces.com/api/v3/chat/completions'

// 创建 AI 对话实例
const summaryHook = useAIStream({
  platform: PlatformType.VOLCANO,
  authToken: '02419daf-d6b6-4d07-bdf7-385f483b5bf7',
  model: AIModelType.DEEPSEEK,
  enableContext: true,
  maxContextMessages: 10,
  isThinking: false,
  thinkStartTag: '<think>',
  thinkEndTag: '</think>'
})

// 解构出来用于控制和显示
const {
  data: summaryData,
  thinkData,
  isLoading: isSummaryLoading,
  error: summaryError,
  lastMessage,
  chat: startAiChat,
  abortFetch: abortSummary
} = summaryHook

// 记录上一次解析的文本长度，用于增量解析
let lastParsedLength = 0;

// 监听AI响应数据，进行实时解析和显示
watch(summaryData, (newVal) => {
  if (newVal) {
    // 更新AI对话内容 - 流式显示
    aiChatRef.value?.addAiResponse({ isStreaming: true, content: newVal })

    // 更新表单内容
    form.value.content = newVal

    // 记录解析长度
    lastParsedLength = newVal.length;
  }
})

// 监听AI思考数据，实时显示
watch(thinkData, (newVal) => {
  // 思考数据会在thinkData中自动累积，不需要额外处理
  // 通过UI的条件渲染，会自动显示思考面板
})

// 当最后一条消息完成时
watch(lastMessage, (newVal) => {
  if (newVal && !isSummaryLoading.value) {
    // 加载完成时更新表单
    form.value.content = newVal;
  }
})

// 监听AI加载状态
watch(isSummaryLoading, (isLoading) => {
  aiLoading.value = isLoading
  if (!isLoading) {
    // 结束流式显示
    aiChatRef.value?.addAiResponse({ isStreaming: true, end: true })
  }
})

// 处理终止AI对话
const handleAbortAI = () => {
  abortSummary()
  aiLoading.value = false
  // 结束流式显示
  aiChatRef.value?.addAiResponse({ isStreaming: true, end: true })
}

// 处理AI对话
const handleAiChat = async (data) => {
  try {
    const { message, context } = data

    // 系统提示词
    const systemPrompt = "你是一个小说助手，请帮助用户完善世界观设定。请按照以下格式输出：\n\n1. 世界背景\n[详细描述世界的基本背景]\n\n2. 世界规则\n[列出世界的主要规则]\n\n3. 特殊设定\n[描述世界的特殊设定]\n\n4. 世界影响\n[说明这些设定对世界的影响]"

    // 开始流式显示
    aiChatRef.value?.addAiResponse({ isStreaming: true, start: true })

    // 使用优化后的AI聊天函数
    await startAiChat(message, systemPrompt)

  } catch (error) {
    console.error('AI生成失败:', error)
    ElMessage.error('AI生成失败，请重试')
    // 结束流式显示
    aiChatRef.value?.addAiResponse({ isStreaming: true, end: true })
  } finally {
    aiLoading.value = false
  }
}

// 处理保存
const handleSave = async () => {
  if (!worldSettingFormRef.value) return

  try {
    await worldSettingFormRef.value.validate()
    saveLoading.value = true

    // 使用字符串类型的 ID
    const submitData = {
      ...form.value,
      id: form.value.id || undefined,
      projectId: form.value.projectId.toString()
    }

    if (currentSetting.value) {
      await updateWorldSetting(submitData)
      ElMessage.success('修改成功')
    } else {
      await addWorldSetting(submitData)
      ElMessage.success('保存成功')
    }
    getWorldSettingInfo()
  } catch (error) {
    if (error?.message) {
      ElMessage.error(error.message)
    } else {
      console.error('保存失败:', error)
      ElMessage.error('保存失败')
    }
  } finally {
    saveLoading.value = false
  }
}

// 添加：处理下一步按钮点击
const handleNextStep = async () => {
  try {
    // 先保存当前世界观设定
    await handleSave()

    // 更新项目状态 - 将当前步骤更新为下一步（角色设定）
    const updatedProject = {
      id: currentProject.value.id,
      currentStep: 2 // 角色设定步骤
    }

    await updateProject(updatedProject)

    // 导航到角色设定页面
    router.push({
      path: '/novel/character',
      query: {
        projectId: currentProject.value.id,
        worldSettingId: currentSetting.value.id
      }
    })

    ElMessage.success('已进入下一步：角色设定')
  } catch (error) {
    console.error('导航到下一步失败:', error)
    ElMessage.error('导航失败，请重试')
  }
}

// 处理上下文开关变化
const handleContextChange = (value) => {
  if (!value) {
    // 当禁用上下文时，提示用户
    ElMessageBox.confirm(
      '禁用上下文后，AI将无法看到之前的对话历史。确定要禁用吗？',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    ).then(() => {
      // 用户确认后，清空对话历史
      aiChatRef.value?.clearHistory()
      enableContext.value = false
      ElMessage.success('已禁用上下文，对话历史已清空')
    }).catch(() => {
      // 用户取消，保持上下文启用状态
      enableContext.value = true
    })
  } else {
    enableContext.value = true
    ElMessage.success('已启用上下文，AI可以看到之前的对话历史')
  }
}

/**
 * 通用的 fetch 流式请求处理器
 * @param input fetch 的参数对象
 * @param onMessage 每次收到 data 的回调，传入解析后的数据
 * @param controller 可选的 AbortController 控制中断
 */
const fetchStream = async (
  input: RequestInfo | URL,
  onMessage: (data: any) => void,
  controller?: AbortController
): Promise<void> => {
  let reader: ReadableStreamDefaultReader | null = null;
  const decoder = new TextDecoder('utf-8');
  let buffer = '';

  try {
    const response = await fetch(input, { signal: controller?.signal });

    if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);
    if (!response.body) throw new Error('响应中没有 body');

    reader = response.body.getReader();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const messages = buffer.split(/\n\n(?=data:)/);
      buffer = messages.pop() || '';

      for (const msg of messages) {
        const data = processMessage(msg.trim());
        if (data) onMessage(data); // 调用回调
      }
    }
  } catch (err) {
    if ((err as Error).name !== 'AbortError') {
      console.error('流式请求出错:', err);
    }
    throw err;
  } finally {
    if (reader) await reader.releaseLock();
  }
};

/**
 * 处理单条消息的解析逻辑（可以抽离出来复用）
 */
const processMessage = (message: string): any | null => {
  if (!message.startsWith('data:')) return null;
  const dataStr = message.slice(5).trim(); // 去除 "data:" 前缀
  try {
    return JSON.parse(dataStr);
  } catch (e) {
    console.warn('无法解析的消息内容:', dataStr);
    return null;
  }
};

onMounted(() => {
  getProjectInfo();
})
</script>

<style lang="scss" scoped>
.novel-page {
  height: calc(100vh - 110px);
  display: flex;

  .novel-page-left,
  .novel-page-right {
    height: 100%;
    display: flex;
    flex-direction: column;
  }

  .novel-page-left {
    .left-panel {
      height: 100%;
      overflow: hidden;
      background: linear-gradient(135deg, #f9fafc, #f1f5fa);
      border-radius: 12px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
      border: 1px solid rgba(214, 222, 235, 0.6);
      display: flex;
      flex-direction: column;

      .thinking-panel {
        background: #f8f5ff;
        border-bottom: 1px solid #e6dcff;
        padding: 16px;
        max-height: 35%;
        overflow-y: auto;

        .thinking-header {
          display: flex;
          align-items: center;
          gap: 8px;
          margin-bottom: 10px;

          .thinking-title {
            font-weight: 600;
            color: #6a3de8;
            font-size: 14px;
          }

          .help-icon {
            color: #6a3de8;
            cursor: pointer;
            font-size: 14px;
          }
        }

        .thinking-content {
          white-space: pre-wrap;
          font-family: monospace;
          font-size: 13px;
          color: #555;
          line-height: 1.5;
        }
      }
    }
  }

  .novel-page-right {
    .content-header {
      padding: 16px 24px;
      background: linear-gradient(90deg, #f9fafc, #f1f5fa);
      border-radius: 12px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
      margin-bottom: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      border: 1px solid rgba(214, 222, 235, 0.6);

      .project-info {
        display: flex;
        align-items: center;
        gap: 14px;

        .project-title {
          font-size: 16px;

          .label {
            color: #606266;
            font-weight: 500;
          }

          .value {
            font-weight: 600;
            color: #2c3e50;
          }
        }

        .project-tag {
          font-size: 13px;
        }
      }

      .action-buttons {
        display: flex;
        gap: 12px;
      }
    }

    .content-body {
      flex: 1;
      background: white;
      border-radius: 12px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
      border: 1px solid rgba(214, 222, 235, 0.6);
      overflow: hidden;

      .form-container {
        height: 100%;
        padding: 24px;

        .setting-form {
          height: 100%;

          :deep(.el-form-item__label) {
            font-weight: 500;
            color: #2c3e50;
          }

          :deep(.el-input__wrapper) {
            box-shadow: 0 0 0 1px #dcdfe6 inset;
            border-radius: 8px;
            transition: all 0.3s;

            &:hover, &:focus-within {
              box-shadow: 0 0 0 1px #409eff inset;
            }
          }

          .content-editor {
            border: 1px solid #dcdfe6;
            border-radius: 8px;
            overflow: hidden;
            width: 100%;

            .editor-toolbar {
              display: flex;
              justify-content: space-between;
              align-items: center;
              padding: 10px 16px;
              background: #f5f7fa;
              border-bottom: 1px solid #dcdfe6;

              .toolbar-title {
                font-size: 14px;
                font-weight: 500;
                color: #606266;
              }

              .ai-status {
                font-size: 13px;
                color: #409eff;
                display: flex;
                align-items: center;
                gap: 6px;

                .el-icon-loading {
                  animation: rotating 2s linear infinite;
                }
              }
            }

            .content-textarea {
              :deep(.el-textarea__inner) {
                border: none;
                border-radius: 0;
                padding: 16px;
                font-size: 15px;
                line-height: 1.8;
                box-shadow: none;

                &:focus {
                  box-shadow: none;
                }
              }
            }
          }
        }
      }
    }
  }
}

@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>

